from Drawable import Drawable
import time
import sys
import Math
import math
import Debug
import pygame
import UAI
import Helper
from copy import copy

class Movable(Drawable):
    name    = "Movable"
    pos     = (0, 0)
    lastpos = (0, 0)
    movable = 1
    angle   = 0
    speed   = 4
    targets = []
    knownpath = -1
    
    def __init__(self, pos, target = False):
        Drawable.__init__(self, pos)
        self.pos             = pos
        self.lastpos         = pos
        self.rect.center     = pos
        self.testrect        = copy(self.rect)
        self.testrect.width  = self.speed
        self.testrect.height = self.speed
        self.targets = []
        
        if target:
            self.targets.append(target)


    def isAtTarget(self, target):
        self.testrect.center = self.rect.center
        if self.testrect.collidepoint(target):
            if self.rect.center != target:
                self.rect.center = target
            return True
        return False

    def isLastTarget(self, target):
        if self.hasTarget():
            return self.targets[-1] == target
        else:
            self.knownpath = 0
            return True
    
    def istargetHidden(self, target):
        return Helper.obsticleInBetween(self.rect, target)
            
    def hasTarget(self):
        if len(self.targets):
            return True
        else:
            return False
        
    def hasKnownPath(self):
        if self.knownpath > 0:
            return True
        else:
            return False
        
    def getNextTarget(self):
        if self.hasTarget():
            return self.targets[0]
        else:
            return self.rect.center
    
    def findPath(self, target):
        Debug.log('Path finding ' + str(self.rect.center)[1:-1] + ' -> ' + str(target)[1:-1], False)
        starttime = time.time()
        node = UAI.pathfinding.findPath(self.rect.center, target)
        searchtime = time.time() - starttime
        if not node: 
            Debug.log('No path found(' + str(round(searchtime, 4)) + 's)')
            return
        Debug.log('Success (' + str(round(searchtime, 4)) + 's', False)
        if UAI.DEBUG:
            Debug.drawPath(node, (255,0,0))
        node = self.smoothPath(node)
        smoothtime = time.time() - starttime - searchtime
        Debug.log(str(round(smoothtime, 4)) + 's ' + str(round(smoothtime + searchtime, 4)) +  's)')
        if UAI.DEBUG:
            Debug.drawPath(node, (0,255,0))
        while node:
            self.addTarget(node.pos, 0, True)
            node = node.parent
    
    def smoothPath(self, node):
        returnnode = node
        testrect = copy(self.rect)
        while node:
            if node.parent:
                if node.parent.parent:
                    testrect.center = node.parent.parent.pos
                    if not Helper.obsticleInBetween(testrect, node.pos):
                        node.parent = node.parent.parent
                        continue
            node = node.parent
        return returnnode
            
    def run(self):
        target = self.getNextTarget()
        if self.isAtTarget(target):
            if self.isLastTarget(target):
                self.stop()
                return
            else:
                self.targets.pop(0)
                self.knownpath -= 1
                target = self.getNextTarget()
        if not self.hasKnownPath():
            if self.istargetHidden(target):
                self.findPath(target)
            else:
                self.knownpath += 1
        self.moveTowardsTarget(target)
        
    def moveTowardsTarget(self, target):
        self.angle, self.distance = Math.getAngleAndDistanceOfTwoPoints(self.rect.center, target)
        dx, dy = Math.getPointOfAngleAndDistance(self.angle, self.speed)
        posx, posy = self.pos
        posx += dx
        posy += dy
        self.pos = (posx, posy)
        self.lastpos = self.rect.center
        self.rect.center = self.pos
    
    def cancelMove(self):
        '''
        TODO: This is broken
        '''
        self.rect.center = self.lastpos
        self.pos = self.lastpos
    
    def addTarget(self, target, index = -1, known = False):
        if index == -1:
            self.targets.append(target)
        else:
            self.targets.insert(index, target)
        if known:
            self.knownpath += 1
    
    def collision(self):
        self.cancelMove()
        self.stop()
    
